home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 Extra Demos / SWFastLine Scrolling Test / Scrolling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-25  |  22.7 KB  |  842 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c
  3. //
  4. // By Vern Jensen. Created in August of 1995
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11. #include <SWFastLine.h>
  12.  
  13. #include "SWApplication.h"
  14. #include "Scrolling Demo.h"
  15.  
  16.  
  17. #define    kFullScreenWindow            true        // Try me full screen!
  18. #define kWorldRectInset                0            // Make the SpriteWorld smaller?
  19. #define    kInterlacedMode                false        // Turns Interlaced mode on/off
  20. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  21. #define kMaxFPS                        30            // Set to 0 for unrestricted speed
  22.  
  23.  
  24. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  25. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  26.                                                 // (try 1!)
  27.  
  28. #define kSpriteMoveDistance            80            // How far the sprite can move from
  29.                                                 // the center of the screen, in pixels.
  30.                                                 // Try making this value higher!
  31.  
  32.     // Number of ticks to wait before changing tile image; 0 = change every frame
  33. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  34. #define kWallFrameRate                120            // How often wall changes frames
  35.  
  36. #define kBWPictResIDOffset            100
  37. #define kTileWidth                    40
  38. #define kTileHeight                    40
  39. #define kTileMapRows                100
  40. #define kTileMapCols                150
  41.  
  42. #define kStartRow                    5            // Starting position of sprite
  43. #define kStartCol                    5            // in tile col and row
  44.  
  45.  
  46. #define    kLeftArrowKey                0x7B
  47. #define    kRightArrowKey                0x7C
  48. #define    kDownArrowKey                0x7D
  49. #define    kUpArrowKey                    0x7E
  50.  
  51. #define    kLeftKeyPad                    0x56
  52. #define    kRightKeyPad                0x58
  53. #define    kDownKeyPad                    0x54
  54. #define    kUpKeyPad                    0x5B
  55.  
  56. #define kEscKey                        0x35
  57.  
  58.  
  59. #define kNoKey                        0
  60. #define kLeftKey                    1
  61. #define kUpKey                        2
  62. #define kRightKey                    3
  63. #define kDownKey                    4
  64.  
  65.  
  66. enum tileIDs
  67. {
  68.     kWallTile,
  69.     kLastWallTile,
  70.     kGrassTile,
  71.     kBlackTile,
  72.     kDiamondTile,
  73.     kDiamondTile2,
  74.     kLastDiamondTile,
  75.     
  76.     kTunnelTile1,
  77.     kTunnelTile2,
  78.     kTunnelTile3,
  79.     kTunnelTile4,
  80.     kTunnelTile5,
  81.     kTunnelTile6,
  82.     kWireTile1,
  83.     kWireTile2,
  84.     
  85.     kMaxNumTiles
  86. };
  87.  
  88.  
  89.  
  90. /***********/
  91. /* Globals */
  92. /***********/
  93.  
  94. SpriteWorldPtr        gSpriteWorldP;
  95. SpriteLayerPtr        gSpriteLayerP;
  96. TileMapStructPtr    gTileMapStructP;
  97. TileMapPtr            gTileMap;
  98. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP;
  99. DrawProcPtr            gSpriteDrawProc, gScreenDrawProc;
  100. DoubleDrawProcPtr    gDoubleRectDrawProc;
  101. WindowPtr            gWindowP;
  102. Rect                gScreenMidRect;
  103.  
  104. Rect                gOldRect, gNewRect;
  105. short                direction;
  106. short                hDelta, vDelta;
  107.  
  108.  
  109. long                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  110. long                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  111.  
  112. struct moveKeys        // Keeps track of which keys are up and which are down
  113. {
  114.     Boolean    up;
  115.     Boolean    right;
  116.     Boolean    down;
  117.     Boolean    left;
  118. } gKeys;
  119.  
  120.  
  121. ///--------------------------------------------------------------------------------------
  122. // Main
  123. ///--------------------------------------------------------------------------------------
  124.  
  125. void    main( void )
  126. {
  127.     Initialize(kNumberOfMoreMastersCalls);
  128.  
  129.     if (SWHasSystem7())
  130.     {
  131.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  132.         SetCursor(*GetCursor(watchCursor));
  133.         
  134.         CreateSpriteWorld();
  135.         SetUpTiling();
  136.         CreateBallSprite();
  137.         CreateDiamondMeterSprite();
  138.         
  139.         SetCursor(&qd.arrow);
  140.         HideCursor();
  141.         
  142.         SetUpAnimation();
  143.         RunAnimation();
  144.         ShutDown();
  145.         
  146.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  147.     }
  148.     else
  149.     {
  150.         CantRunOnThisMachine();
  151.     }
  152. }
  153.  
  154.  
  155. ///--------------------------------------------------------------------------------------
  156. // CreateSpriteWorld
  157. ///--------------------------------------------------------------------------------------
  158.  
  159. void    CreateSpriteWorld( void )
  160. {
  161.     Rect        offscreenRect, worldRect, windRect;
  162.     RgnHandle    mBarUpdateRgn;
  163.     OSErr        err;
  164.     
  165.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  166.     
  167.     if (gWindowP != NULL)
  168.     {
  169.         if ( GetDepthFromWindow(gWindowP) != 8 )
  170.         {
  171.             SetCursor(&qd.arrow);
  172.             StopAlert(130, NULL);
  173.             ExitToShell();
  174.         }
  175.         
  176.         if (kFullScreenWindow == true)
  177.         {
  178.             SizeWindow(gWindowP, qd.screenBits.bounds.right, 
  179.                     qd.screenBits.bounds.bottom, false);
  180.             MoveWindow(gWindowP, 0, 0, false);
  181.         }
  182.         else
  183.         {
  184.                 // Center window in screen
  185.             windRect = gWindowP->portRect;
  186.             CenterRect(&windRect, &qd.screenBits.bounds);
  187.             
  188.                 // Make sure window is aligned to long-word boundaries (for 8-bit mode)
  189.             windRect.left = windRect.left>>2<<2;
  190.             
  191.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  192.         }
  193.         
  194.         ShowWindow(gWindowP);
  195.         SetPort(gWindowP);
  196.         mBarUpdateRgn = SWHideMenuBar(gWindowP); // Must be done *after* showing window!
  197.         EraseRgn(mBarUpdateRgn);
  198.         
  199.         if (kInterlacedMode)
  200.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  201.     }
  202.     else
  203.         CantFindResource();
  204.     
  205.     
  206.     err = SWEnterSpriteWorld();
  207.     FatalError(err);
  208.     
  209.     
  210.     worldRect = gWindowP->portRect;
  211.     InsetRect(&worldRect, kWorldRectInset, kWorldRectInset);
  212.     
  213.     
  214.         // Set size of offscreen area
  215.     offscreenRect = worldRect;
  216.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  217.     
  218.  
  219.         // Make offscreen area evenly divisible by tile width & height
  220.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  221.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  222.     
  223.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  224.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  225.     
  226.         // Create the scrolling sprite world
  227.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  228.             &worldRect, &offscreenRect, 0);
  229.     FatalError(err);
  230.     
  231.             // Create the sprite layer
  232.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  233.     FatalError(err);
  234.     
  235.         // Add it to the world
  236.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);
  237.     
  238.     
  239.         // Determine what DrawProcs to use
  240.     if (gSpriteWorldP->pixelDepth == 8)        // 256 colors
  241.     {
  242.         if (kInterlacedMode)
  243.         {
  244.             gSpriteDrawProc = BP8BitInterlacedMaskDrawProc;
  245.             gScreenDrawProc = BP8BitInterlacedRectDrawProc;
  246.             gDoubleRectDrawProc = BP8BitInterlacedDoubleRectDrawProc;
  247.             SWSetPartialMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
  248.         }
  249.         else
  250.         {
  251.             gSpriteDrawProc = BlitPixie8BitMaskDrawProc;
  252.             gScreenDrawProc = SWStdWorldDrawProc;
  253.             gDoubleRectDrawProc = BlitPixie8BitDoubleRectDrawProc;
  254.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
  255.         }
  256.     }
  257.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )    // Not 256 colors
  258.     {
  259.             // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  260.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  261.         {
  262.             gSpriteDrawProc = BPAllBitInterlacedMaskDrawProc;
  263.             gScreenDrawProc = BPAllBitInterlacedRectDrawProc;
  264.             SWSetPartialMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
  265.             if (gSpriteWorldP->pixelDepth == 16)
  266.                 gDoubleRectDrawProc = BP16BitInterlacedDoubleRectDrawProc;
  267.         }
  268.         else
  269.         {
  270.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  271.             gScreenDrawProc = BlitPixieAllBitRectDrawProc;
  272.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  273.             if (gSpriteWorldP->pixelDepth == 16)
  274.                 gDoubleRectDrawProc = BlitPixie16BitDoubleRectDrawProc;
  275.         }
  276.     }
  277.     else
  278.     {
  279.         gSpriteDrawProc = SWStdSpriteDrawProc;
  280.         gScreenDrawProc = SWStdWorldDrawProc;
  281.         gDoubleRectDrawProc = NULL;
  282.     }
  283. }
  284.     
  285.     
  286. ///--------------------------------------------------------------------------------------
  287. // SetUpTiling
  288. ///--------------------------------------------------------------------------------------
  289.  
  290. void    SetUpTiling( void )    
  291. {
  292.     short        resIDOffset;
  293.     short        row, col;
  294.     OSErr        err;
  295.  
  296.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  297.     FatalError(err);
  298.     
  299.     err = SWCreateTileMap(&gTileMapStructP, kTileMapRows, kTileMapCols);
  300.     FatalError(err);
  301.     
  302.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  303.     gTileMap = gTileMapStructP->tileMap;
  304.     
  305.     SWSetSpriteLayerUnderTileLayer(gSpriteLayerP, 0);
  306.  
  307.         // Determine whether to load B&W or color graphics
  308.     if (gSpriteWorldP->pixelDepth <= 2)
  309.         resIDOffset = kBWPictResIDOffset;
  310.     else
  311.         resIDOffset = 0;
  312.  
  313.         // Load first set of tiles
  314.     err = SWLoadTilesFromPictResource(
  315.         gSpriteWorldP, 
  316.         kWallTile,                // startTileID 
  317.         kLastDiamondTile,        // endTileID
  318.         200 + resIDOffset,        // pictResID
  319.         0,                        // maskResID
  320.         kNoMask,                // maskType
  321.         1,                        // horizBorderWidth
  322.         1);                        // vertBorderHeight
  323.     FatalError(err);
  324.     
  325.         // Load masked set of tiles
  326.     err = SWLoadTilesFromPictResource(
  327.         gSpriteWorldP, 
  328.         kTunnelTile1,            // startTileID 
  329.         kWireTile2,                // endTileID
  330.         201 + resIDOffset,        // pictResID
  331.         401,                    // maskResID
  332.         kFatMask,                // maskType
  333.         1,                        // horizBorderWidth
  334.         1);                        // vertBorderHeight
  335.     FatalError(err);
  336.  
  337.     
  338.         // Set up tileMap
  339.     for (row = 0; row < kTileMapRows; row++)
  340.     {
  341.         for (col = 0; col < kTileMapCols; col++)
  342.         {
  343.             if (row == 0 || col == 0 || row == kTileMapRows-1 || col == kTileMapCols-1)
  344.                 gTileMap[row][col] = kWallTile;
  345.             else if (row > kTileMapRows / 2)
  346.                 gTileMap[row][col] = kWireTile1;
  347.             else if ((row/kDiamondSpace)*kDiamondSpace == row && 
  348.                      (col/kDiamondSpace)*kDiamondSpace == col)
  349.             {
  350.                 gTileMap[row][col] = kDiamondTile;
  351.                 gNumDiamondsInMap++;
  352.             }
  353.             else
  354.                 gTileMap[row][col] = kGrassTile;
  355.         }
  356.     }
  357.     
  358.  
  359.         // Add tunnel to tileMap
  360.     row = kTileMapRows / 2;
  361.  
  362.     for (col = 1; col < kTileMapCols-1; col += 2)
  363.     {
  364.         gTileMap[row][col] = kTunnelTile1;
  365.         gTileMap[row][col+1] = kTunnelTile2;
  366.         gTileMap[row+1][col] = kTunnelTile4;
  367.         gTileMap[row+1][col+1] = kTunnelTile5;
  368.     }
  369. }
  370.  
  371.  
  372. ///--------------------------------------------------------------------------------------
  373. // CreateBallSprite
  374. ///--------------------------------------------------------------------------------------
  375.  
  376. void    CreateBallSprite( void )
  377. {
  378.     OSErr    err;
  379.     
  380.         // Create the ball sprite
  381.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  382.             128, 1, kFatMask);    
  383.     FatalError(err);
  384.     
  385.         // Set up the ball sprite
  386.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  387.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  388.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  389.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  390.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  391. }
  392.  
  393.  
  394. ///--------------------------------------------------------------------------------------
  395. // CreateDiamondMeterSprite
  396. ///--------------------------------------------------------------------------------------
  397.  
  398. void    CreateDiamondMeterSprite( void )
  399. {
  400.     short        spriteResID;
  401.     OSErr        err;
  402.     
  403.         // Calculate resource ID for diamond meter sprite
  404.     if (gSpriteWorldP->pixelDepth <= 2)
  405.         spriteResID = 302;
  406.     else
  407.         spriteResID = 202;
  408.     
  409.         // Create the diamond meter sprite
  410.     err = SWCreateSpriteFromPictResource(gSpriteWorldP,
  411.                 &gDiamondMeterSpriteP, 
  412.                 NULL,            // pointer to memory for sprite
  413.                 spriteResID,     // picture resource id
  414.                 402,            // mask resource id
  415.                 1,                 // max frames
  416.                 kPixelMask);        // mask type
  417.     FatalError(err);
  418.     
  419.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  420.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  421. }
  422.  
  423.  
  424. ///--------------------------------------------------------------------------------------
  425. // SetUpAnimation
  426. ///--------------------------------------------------------------------------------------
  427.  
  428. void    SetUpAnimation( void )
  429. {
  430.     Rect        moveBoundsRect;
  431.     
  432.     SWLockSpriteWorld(gSpriteWorldP);
  433.     
  434.         // Set up data used by the SmoothScrollingWorldMoveProc
  435.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  436.     CenterRect( &gScreenMidRect, &gSpriteWorldP->backRect );
  437.     
  438.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  439.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  440.     SWSetCleanUpSpriteWorld(gSpriteWorldP);
  441.     
  442.         // movement boundary = size of tileMap
  443.     SetRect(&moveBoundsRect, 0,0, kTileMapCols * kTileWidth, kTileMapRows * kTileHeight);
  444.     
  445.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  446.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  447.     
  448.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  449.     
  450.         // Move visScrollRect to starting sprite position
  451.     SWMoveVisScrollRect(gSpriteWorldP, 
  452.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  453.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  454.     
  455.         // Set starting position of diamond meter sprite
  456.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  457.  
  458.     SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  459.     SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  460.     SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  461.     
  462.     SWSetPostEraseCallBack(gSpriteWorldP, EraseRectOffscreen);
  463.     SWSetPostDrawCallBack(gSpriteWorldP, DrawRectOffscreen);
  464.     
  465.         // Make sure CopyBits, if used, doesn't try to colorize things
  466.     SWSetPortToWindow(gSpriteWorldP);
  467.     ForeColor(blackColor);
  468.     BackColor(whiteColor);
  469.     
  470.     SetRect(&gOldRect, 50, 50, 300, 300);
  471.     gNewRect = gOldRect;
  472.     direction = 1;
  473.     hDelta = 2;
  474.     vDelta = 2;
  475.     
  476.     SWDrawTilesInBackground(gSpriteWorldP);
  477.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  478. }
  479.  
  480.  
  481. ///--------------------------------------------------------------------------------------
  482. //  RunAnimation
  483. ///--------------------------------------------------------------------------------------
  484.  
  485. void    RunAnimation( void )
  486. {
  487.     unsigned long        frames;
  488.         
  489.     frames = 0;
  490.     StartTimer();
  491.  
  492.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  493.  
  494.     while (!Button())
  495.     {
  496.         SWProcessScrollingSpriteWorld(gSpriteWorldP);
  497.         
  498.             // We call this in case the Control Strip or something changes our window's visRgn
  499.         KeepMenuBarHidden(gWindowP);
  500.  
  501.             // Move diamond meter sprite to new visScrollRect location
  502.         DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  503.         
  504.             // Make sure no errors occurred during a MoveProc, etc.
  505.         FatalError( SWStickyError() );
  506.     
  507.         SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  508.         
  509.         if (gSpriteWorldP->frameHasOccurred)
  510.         {
  511.             frames++;
  512.             ProcessRect();
  513.         }
  514.     }
  515.     
  516.     
  517.     ShowResults(frames);
  518.     SWShowMenuBar(gWindowP);
  519. }
  520.  
  521.  
  522. ///--------------------------------------------------------------------------------------
  523. //  ProcessRect
  524. ///--------------------------------------------------------------------------------------
  525.  
  526. void    ProcessRect( void )
  527. {
  528.     OffsetRect(&gNewRect, 2, 2);
  529.     
  530.     if (direction > 0)
  531.     {
  532.         InsetRect(&gNewRect, -1, -1);
  533.         if (SW_RECT_WIDTH(gNewRect) > 800)
  534.             direction = -1;
  535.     }
  536.     else
  537.     {
  538.         InsetRect(&gNewRect, 1, 1);
  539.         if (SW_RECT_WIDTH(gNewRect) < 50)
  540.             direction = 1;
  541.     }
  542.  
  543. }
  544.  
  545.  
  546. ///--------------------------------------------------------------------------------------
  547. //  EraseRectOffscreen
  548. ///--------------------------------------------------------------------------------------
  549.  
  550. SW_FUNC void    EraseRectOffscreen( SpriteWorldPtr spriteWorldP )
  551. {
  552.     Point    srcPoint, dstPoint;
  553.     
  554.     srcPoint.h = gOldRect.left;
  555.     srcPoint.v = gOldRect.top;
  556.     dstPoint.h = gOldRect.right;
  557.     dstPoint.v = gOldRect.bottom;
  558.     SWCopyLineInScrollingWorld(spriteWorldP, spriteWorldP->backFrameP, 
  559.         spriteWorldP->workFrameP, srcPoint, dstPoint, &spriteWorldP->oldVisScrollRect);
  560.     
  561.     srcPoint.h = gOldRect.right;
  562.     dstPoint.h = gOldRect.left;
  563.     SWCopyLineInScrollingWorld(spriteWorldP, spriteWorldP->backFrameP, 
  564.         spriteWorldP->workFrameP, srcPoint, dstPoint, &spriteWorldP->oldVisScrollRect);
  565.     
  566.     SWCopyFrameRectInScrollingWorld(spriteWorldP, spriteWorldP->backFrameP, 
  567.         spriteWorldP->workFrameP, &gOldRect, &spriteWorldP->oldVisScrollRect);
  568. }
  569.  
  570.  
  571. ///--------------------------------------------------------------------------------------
  572. //  DrawRectOffscreen
  573. ///--------------------------------------------------------------------------------------
  574.  
  575. SW_FUNC void    DrawRectOffscreen( SpriteWorldPtr spriteWorldP )
  576. {
  577.     Point    srcPoint, dstPoint;
  578.     
  579.     SWDrawFrameRectInScrollingWorld(spriteWorldP, spriteWorldP->workFrameP, 
  580.         &gNewRect, 205);
  581.     
  582.     srcPoint.h = gNewRect.left;
  583.     srcPoint.v = gNewRect.top;
  584.     dstPoint.h = gNewRect.right;
  585.     dstPoint.v = gNewRect.bottom;
  586.     SWDrawLineInScrollingWorld(spriteWorldP, spriteWorldP->workFrameP, srcPoint, dstPoint, 100);
  587.     
  588.     srcPoint.h = gNewRect.right;
  589.     dstPoint.h = gNewRect.left;
  590.     SWDrawLineInScrollingWorld(spriteWorldP, spriteWorldP->workFrameP, srcPoint, dstPoint, 100);
  591.     
  592.     gOldRect = gNewRect;
  593. }
  594.  
  595.  
  596. ///--------------------------------------------------------------------------------------
  597. //  ShutDown (clean up and dispose of the SpriteWorld)
  598. ///--------------------------------------------------------------------------------------
  599.  
  600. void    ShutDown( void )
  601. {
  602.     SWDisposeSpriteWorld(&gSpriteWorldP);
  603.     SWExitSpriteWorld();
  604.     
  605.     FlushEvents(everyEvent, 0);
  606.     ShowCursor();
  607. }
  608.  
  609.  
  610. ///--------------------------------------------------------------------------------------
  611. //  TileChangeProc
  612. ///--------------------------------------------------------------------------------------
  613.  
  614. SW_FUNC void TileChangeProc(
  615.     SpriteWorldPtr spriteWorldP)
  616. {
  617.     short            curImage;
  618.     static short    wallDelay = 0, diamondDelay = 0;
  619.     static short    oldTicks = 0;
  620.     short            ticksPassed, ticks;
  621.     
  622.         // Initialize oldTicks the first time this function is called
  623.     if (oldTicks == 0)
  624.         oldTicks = TickCount();
  625.     
  626.     ticks = TickCount();
  627.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  628.     oldTicks = ticks;
  629.     
  630.         // kWallTile
  631.     wallDelay += ticksPassed;
  632.     if (wallDelay >= kWallFrameRate)
  633.     {
  634.         curImage = spriteWorldP->curTileImage[kWallTile];
  635.         if (curImage < kLastWallTile)
  636.             curImage++;
  637.         else
  638.             curImage = kWallTile;
  639.         
  640.         SWChangeTileImage(spriteWorldP, kWallTile, curImage);
  641.         wallDelay = 0;
  642.     }
  643.     
  644.     
  645.         // kDiamondTile
  646.     diamondDelay += ticksPassed;
  647.     if (diamondDelay >= kDiamondFrameRate)
  648.     {
  649.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  650.         if (curImage < kLastDiamondTile)
  651.             curImage++;
  652.         else
  653.             curImage = kDiamondTile;
  654.         
  655.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  656.         diamondDelay = 0;
  657.     }
  658. }
  659.  
  660.  
  661. ///--------------------------------------------------------------------------------------
  662. //  KeySpriteMoveProc
  663. ///--------------------------------------------------------------------------------------
  664.  
  665. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  666. {
  667.     short    row, col;
  668.     short    rowDelta, colDelta;
  669.     short    tile;
  670.     
  671.     UpdateKeys();    // Put the latest key values in the keys structure
  672.     
  673.     
  674.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  675.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  676.  
  677.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  678.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  679.     {
  680.         tile = gTileMap[row][col];
  681.         
  682.             // Leave black trail behind sprite
  683.         if (tile == kGrassTile || tile == kDiamondTile)
  684.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  685.         else if (tile == kTunnelTile2 || tile == kTunnelTile5 || tile == kWireTile1)
  686.             SWDrawTile(gSpriteWorldP, 0, row, col, tile+1);
  687.             
  688.         if (tile == kDiamondTile)
  689.         {
  690.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  691.             UpdateDiamondMeter();    // Update meter
  692.         }
  693.         
  694.  
  695.         rowDelta = 0;
  696.         colDelta = 0;
  697.         
  698.         if (gKeys.left)
  699.             colDelta = -1;
  700.         else if (gKeys.right)
  701.             colDelta = 1;
  702.         else if (gKeys.up)
  703.             rowDelta = -1;
  704.         else if (gKeys.down)
  705.             rowDelta = 1;
  706.         
  707.                 
  708.         
  709.         tile = gTileMap[row + rowDelta][col + colDelta];
  710.         
  711.         if (tile != kWallTile && tile != kTunnelTile1 && tile != kTunnelTile4)
  712.         {
  713.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  714.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  715.         }
  716.         else
  717.         {
  718.             srcSpriteP->vertMoveDelta = 0;
  719.             srcSpriteP->horizMoveDelta = 0;
  720.         }
  721.     }
  722.     
  723.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  724.     
  725.     
  726.         // Set the sprite to be redrawn each frame, since we never know when a line
  727.         // might erase it.
  728.     srcSpriteP->needsToBeDrawn = true;
  729. }
  730.  
  731.  
  732. ///--------------------------------------------------------------------------------------
  733. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  734. ///--------------------------------------------------------------------------------------
  735.  
  736. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  737. {
  738.         // Move sprite to top-left corner of current visScrollRect location
  739.     SWMoveSprite(srcSpriteP, 
  740.         gSpriteWorldP->visScrollRect.left + 10, 
  741.         gSpriteWorldP->visScrollRect.top + 10);
  742.     
  743.         // Set the sprite to be redrawn each frame, since we never know when a line
  744.         // might erase it.
  745.     srcSpriteP->needsToBeDrawn = true;
  746. }
  747.  
  748.  
  749. ///--------------------------------------------------------------------------------------
  750. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  751. ///--------------------------------------------------------------------------------------
  752.  
  753. SW_FUNC void UpdateDiamondMeter( void )
  754. {
  755.     double    percent;
  756.     Rect    meterRect;
  757.     
  758.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  759.     
  760.         // 108 = length of meter; 17 = offset from start of meter
  761.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  762.     
  763.     
  764.         // Set port to our sprite's framePort GWorld
  765.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  766.     
  767.     ForeColor(magentaColor);
  768.     PaintRect(&meterRect);
  769.     
  770.         // IMPORTANT: Set the color back when done! (In case CopyBits is used later)
  771.     ForeColor(blackColor);
  772.     
  773.     
  774.         // Set port to our sprite's pixel mask GWorld
  775.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  776.     
  777.         // Mask image is inverted when in 8-bit or less
  778.     if (gSpriteWorldP->pixelDepth <= 8)
  779.         ForeColor(whiteColor);
  780.     else
  781.         ForeColor(blackColor);
  782.     
  783.     PaintRect(&meterRect);
  784.     ForeColor(blackColor);
  785.     
  786.     
  787.         // Set sprite to be redrawn, since we've changed its image
  788.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  789. }
  790.  
  791.  
  792. ///--------------------------------------------------------------------------------------
  793. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  794. ///--------------------------------------------------------------------------------------
  795.  
  796. SW_FUNC void SmoothScrollingWorldMoveProc(
  797.     SpriteWorldPtr spriteWorldP,
  798.     SpritePtr followSpriteP)
  799. {    
  800.     short    screenMidRectTop, screenMidRectLeft;
  801.     
  802.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  803.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  804.     
  805.     
  806.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  807.         (followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
  808.     
  809.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  810.         (followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
  811.     
  812.     if (kInterlacedMode)
  813.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  814. }
  815.  
  816.  
  817. ///--------------------------------------------------------------------------------------
  818. //  UpdateKeys (Put the latest key values in the keys structure)
  819. ///--------------------------------------------------------------------------------------
  820.  
  821. void    UpdateKeys( void )
  822. {
  823.     EventRecord        event;
  824.     short            theKey;
  825.     Boolean            isDown;
  826.     
  827.     while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
  828.     {
  829.         theKey = (event.message & keyCodeMask) >> 8;
  830.         isDown = (event.what != keyUp);
  831.         
  832.         if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  833.             gKeys.left = isDown;
  834.         else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  835.             gKeys.right = isDown;
  836.         else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  837.             gKeys.down = isDown;
  838.         else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  839.             gKeys.up = isDown;
  840.     }
  841. }
  842.